pub fn base64_mod_encode(data: &[u8]) -> String {
    use base64::{engine, alphabet, Engine as _};

    let alphabet = alphabet::Alphabet::new(
        "LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA"
    ).unwrap();
    let engine_mod = engine::GeneralPurpose::new(
        &alphabet, 
        engine::GeneralPurposeConfig::new()
    );
    let encoded = engine_mod.encode(data);
    encoded
}

pub fn byte_to_hex(data: &[u8]) -> String {
    use std::fmt::Write;

    let mut s = String::with_capacity(2 * data.len());
    for byte in data {
        write!(s, "{:02X}", byte).unwrap();
    }
    s
}

pub fn hex_hmac_md5(data: &str, key: &str) -> String {
    use hmac::{Hmac, Mac};
    use md5::Md5;
    type HmacMd5 = Hmac<Md5>;

    let mut hmac = HmacMd5::new_from_slice(key.as_bytes()).unwrap();
    hmac.update(data.as_bytes());
    let result = hmac.finalize();
    let code_bytes = result.into_bytes();
    byte_to_hex(&code_bytes)
}

pub fn hex_sha1(data: &str) -> String {
    use sha1::{Sha1, Digest};

    let mut hasher = Sha1::new();
    hasher.update(data.as_bytes());
    let code_bytes = hasher.finalize();
    byte_to_hex(&code_bytes)
}

pub fn get_timestamp() -> String {
    let now = chrono::Local::now();
    now.timestamp_millis().to_string()
}

pub fn get_datetime() -> String {
    let now = chrono::Local::now();
    now.format("%Y/%m/%d %H:%M:%S").to_string()
}